<!DOCTYPE html>
<html >
<head>
    <meta charset="utf-8">
    <title> JVM监控 GC监控信息 </title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="layui/css/layui.css" media="all">
    <link rel="stylesheet" href="css/monitor.css" media="all">
    <!-- 注意：如果你直接复制所有代码到本地，上述css路径需要改成你本地的 -->
</head>
<body>
<blockquote class="layui-elem-quote layui-text font16">
    Java虚拟机统计信息监视工具 <span class="font12">(Java Virtual Machine Statistics Monitoring Tool)</span>
</blockquote>
<div class="layui-fluid" id="renderContent">

</div>
<script src="js/jquery-3.4.0.min.js" charset="utf-8"></script>
<script src="layui/layui.js" charset="utf-8"></script>
<!-- 注意：如果你直接复制所有代码到本地，上述js路径需要改成你本地的 -->
<script type="text/javascript">
    // 最大次数 100次
    var globalTimes = {};
    // 最大请求次数
    var MAX_COUNT = 100;
    /**
     *  布局页面加载内容
     * */
    var layout =[
        {code:'class',name:'类加载统计',hide:true},
        {code:'compiler',name:'编译统计',hide:true },
        {code:'gc',name:'垃圾回收统计' },
        {code:'gccapacity',name:'堆内存统计' },
        {code:'gcnew',name:'新生代垃圾回收统计' },
        {code:'gcnewcapacity',name:'新生代内存统计' },
        {code:'gcold',name:'老年代垃圾回收统计' },
        {code:'gcoldcapacity',name:'老年代内存统计' },
        // {code:'gcpermcapacity',name:'永久代空间统计' },
        {code:'gcmetacapacity',name:'元数据空间统计' ,hide:true},
        {code:'gcutil',name:'总结垃圾回收统计'},
        {code:'printcompilation',name:'编译方法统计',hide:true }
    ]


    /**
     * 对象替换
     * */
    function replaceAll(str,param){
        var newstr = str;
        // 对象替换
        for(var key in param){
            var reg = new RegExp('{'+ key +'}', "g" )
            newstr = newstr.replace( reg , param[key] )
        }

        return newstr;
    }        /**
         *  启动类
         **/
        $(function(){
            // 加载部署页面
            var _renderContentHtml = $("#renderContentHtml").html();
            var html  = "";
            for(var i=0,len = layout.length ;i < len ;i++){
                // 替换模板
                html = html + replaceAll(_renderContentHtml,layout[i]);
                // 替换模板
                html = replaceAll(html,{i:i+1});
            }
            $("#renderContent").html(html);
            // 加载页面数据
            loadData()
            // bind click
            // 初始化表单
            layui.use(['form', 'layedit', 'laydate','layer'], function(){
                var layer = layui.layer;
                var timers = {};
                // 绑定checkbox
                layui.form.on('checkbox(like)', function(data){
                    if(data.elem.checked){
                         timers[data.value] = setInterval( function (){
                             if(globalTimes[data.value] > MAX_COUNT){
                                 if(timers[data.value]){
                                     clearInterval(timers[data.value])
                                 }
                             }
                            // 请求地址
                            var url = "v1/api/stat/command.json?command=" + data.value + "&isContainHeader=false";
                            (
                                function (_myurl) {
                                    // 处理数据
                                    _ajax(_myurl,function (data) {
                                        var command = data.command;
                                        // 全局计数器
                                        globalTimes[command] =  globalTimes[command] + 1;
                                        // 设置表格
                                        if(data.headers){
                                            var _tableHeadhtml = "<tr>";
                                            for(var i=0,len= data.headers.length;i< len;i++){
                                                _tableHeadhtml = _tableHeadhtml + "<td class='wd90'>" + data.headers[i] + "</td>";
                                            }
                                            _tableHeadhtml = _tableHeadhtml + "</tr>";
                                            // 添加头部
                                            $("#"+command+"tableHead").html(_tableHeadhtml);
                                        }
                                        // 设置表格
                                        if(data.rows){
                                            var _tableBodyhtml = "<tr>";
                                            for(var i=0,len= data.rows.length;i< len;i++){
                                                _tableBodyhtml = _tableBodyhtml + "<td>" + data.rows[i] + "</td>";
                                            }
                                            _tableBodyhtml = _tableBodyhtml + "</tr>";
                                            // 添加头部
                                            $("#"+command+"tableBody").append(_tableBodyhtml);
                                        }
                                    })
                                }
                            )(url)
                        },3000)
                    }
                    else{
                        if(timers[data.value]){
                            clearInterval(timers[data.value]);
                        }
                    }

                });

                var tips;
                $('.mytips').on({
                    mouseenter:function(){
                        var that = this;
                        var tipId = $(that).data("tipId");
                        var _html = $("#" + tipId+ "HelpTip").html();
                        tips =layer.tips(_html,
                            that,{tips:[2,'#f2f2f2'],time:0,area: 'auto',maxWidth:500});
                    },
                    mouseleave:function(){
                        layer.close(tips);
                    }
                });

            });
        });

    /**
     *  加载页面内容
     * */
    function loadData(){
        for(var i=0,len = layout.length ;i < len ;i++){
            // 请求地址
            var url = "v1/api/stat/command.json?command=" + layout[i].code + "&isContainHeader=true";
            (
                function (myurl) {
                    // 处理数据
                    _ajax(myurl,function (data) {
                        var command = data.command;
                        // 设置表格
                        if(data.headers){
                            var _tableHeadhtml = "<tr>";
                            for(var i=0,len= data.headers.length;i< len;i++){
                                _tableHeadhtml = _tableHeadhtml + "<td class='wd90'>" + data.headers[i] + "</td>";
                            }
                            _tableHeadhtml = _tableHeadhtml + "</tr>";
                            // 添加头部
                            $("#"+command+"tableHead").html(_tableHeadhtml);
                        }
                        // 设置表格
                        if(data.rows){
                            var _tableBodyhtml = "<tr>";
                            for(var i=0,len= data.rows.length;i< len;i++){
                                _tableBodyhtml = _tableBodyhtml + "<td>" + data.rows[i] + "</td>";
                            }
                            _tableBodyhtml = _tableBodyhtml + "</tr>";
                            // 添加头部
                            $("#"+command+"tableBody").html(_tableBodyhtml);
                        }
                    })
                }
            )(url)

        }
    }

    /**
     * url:请求的地址
     * callback:回调函数
     * */
    function  _ajax(url,callback){
        $.ajax({
            type: "GET",
            url: url,
            dataType: "json",
            success: function(data){
                if(data.code == 200) {
                    // 显示内容
                    callback(data.data)
                }
            }
        });
    }
</script>

<script type="text/html" id="renderContentHtml">
    <div class="layui-card">
        <div class="layui-card-header">
            <blockquote class="layui-elem-quote">
                <div class="layui-form">
                    <div class="layui-form-item">
                        <label class="layui-form-label unsetwidth">{i}、{name} </label>
                        <div class="layui-input-block {hide}">
                            <input type="checkbox" name="{code}" lay-filter="like" title="3s自动刷新" value="{code}">
                            <i id="tipid{i}" class="layui-icon cursor layui-icon-help mytips" data-tip-id="{code}"></i>
                        </div>
                    </div>
                </div>

            </blockquote>
        </div>
        <div class="layui-card-body">
            <table lay-even lay-skin="line" lay-size="lg" class="layui-table">
                <thead id="{code}tableHead">
                </thead>
                <tbody id="{code}tableBody" class="layui-table-body">
                </tbody>
            </table>
        </div>
    </div>
</script>

<!--帮助说明：-->
<script type="text/html" id="classHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        Loaded:加载class的数量<br/>
        Bytes：所占用空间大小<br/>
        Unloaded：未加载数量<br/>
        Bytes:未加载占用空间<br>
        Time：时间
    </blockquote>
</script>
<!--帮助说明：-->
<script type="text/html" id="compilerHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        Compiled：编译数量<br/>
        Failed：失败数量<br/>
        Invalid：不可用数量<br/>
        Time：时间<br/>
        FailedType：失败类型<br/>
        FailedMethod：失败的方法
    </blockquote>
</script>

<!--帮助说明：-->
<script type="text/html" id="gcHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        S0C：第一个幸存区的大小<br/>
        S1C：第二个幸存区的大小<br/>
        S0U：第一个幸存区的使用大小<br/>
        S1U：第二个幸存区的使用大小<br/>
        EC：伊甸园区的大小<br/>
        EU：伊甸园区的使用大小<br/>
        OC：老年代大小<br/>
        OU：老年代使用大小<br/>
        MC：方法区大小<br/>
        MU：方法区使用大小<br/>
        CCSC:压缩类空间大小<br/>
        CCSU:压缩类空间使用大小<br/>
        YGC：年轻代垃圾回收次数<br/>
        YGCT：年轻代垃圾回收消耗时间<br/>
        FGC：老年代垃圾回收次数<br/>
        FGCT：老年代垃圾回收消耗时间<br/>
        GCT：垃圾回收消耗总时间
    </blockquote>
</script>

<!--帮助说明：-->
<script type="text/html" id="gccapacityHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        NGCMN：新生代最小容量<br/>
        NGCMX：新生代最大容量<br/>
        NGC：当前新生代容量<br/>
        S0C：第一个幸存区大小<br/>
        S1C：第二个幸存区的大小<br/>
        EC：伊甸园区的大小<br/>
        OGCMN：老年代最小容量<br/>
        OGCMX：老年代最大容量<br/>
        OGC：当前老年代大小<br/>
        OC:当前老年代大小<br/>
        MCMN:最小元数据容量<br/>
        MCMX：最大元数据容量<br/>
        MC：当前元数据空间大小<br/>
        CCSMN：最小压缩类空间大小<br/>
        CCSMX：最大压缩类空间大小<br/>
        CCSC：当前压缩类空间大小<br/>
        YGC：年轻代gc次数<br/>
        FGC：老年代GC次数
    </blockquote>
</script>
<!--帮助说明：-->
<script type="text/html" id="gcnewHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        S0C：第一个幸存区大小<br/>
        S1C：第二个幸存区的大小<br/>
        S0U：第一个幸存区的使用大小<br/>
        S1U：第二个幸存区的使用大小<br/>
        TT:对象在新生代存活的次数<br/>
        MTT:对象在新生代存活的最大次数<br/>
        DSS:期望的幸存区大小<br/>
        EC：伊甸园区的大小<br/>
        EU：伊甸园区的使用大小<br/>
        YGC：年轻代垃圾回收次数<br/>
        YGCT：年轻代垃圾回收消耗时间
    </blockquote>
</script>

<!--帮助说明：-->
<script type="text/html" id="gcnewcapacityHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        NGCMN：新生代最小容量<br/>
        NGCMX：新生代最大容量<br/>
        NGC：当前新生代容量<br/>
        S0CMX：最大幸存1区大小<br/>
        S0C：当前幸存1区大小<br/>
        S1CMX：最大幸存2区大小<br/>
        S1C：当前幸存2区大小<br/>
        ECMX：最大伊甸园区大小<br/>
        EC：当前伊甸园区大小<br/>
        YGC：年轻代垃圾回收次数<br/>
        FGC：老年代回收次数
    </blockquote>
</script>

<!--帮助说明：-->
<script type="text/html" id="gcoldHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        MC：方法区大小<br/>
        MU：方法区使用大小<br/>
        CCSC:压缩类空间大小<br/>
        CCSU:压缩类空间使用大小<br/>
        OC：老年代大小<br/>
        OU：老年代使用大小<br/>
        YGC：年轻代垃圾回收次数<br/>
        FGC：老年代垃圾回收次数<br/>
        FGCT：老年代垃圾回收消耗时间<br/>
        GCT：垃圾回收消耗总时间
    </blockquote>
</script>

<!--帮助说明：-->
<script type="text/html" id="gcoldcapacityHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        OGCMN：老年代最小容量<br/>
        OGCMX：老年代最大容量<br/>
        OGC：当前老年代大小<br/>
        OC：老年代大小<br/>
        YGC：年轻代垃圾回收次数<br/>
        FGC：老年代垃圾回收次数<br/>
        FGCT：老年代垃圾回收消耗时间<br/>
        GCT：垃圾回收消耗总时间
    </blockquote>
</script>
<!--帮助说明：-->
<script type="text/html" id="gcpermcapacityHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        PGCMN:最小永久代容量<br/>
        PGCMX：最大永久代容量<br/>
        PGC：当前新生成的永久代空间大小<br/>
        PC ：永久代空间大小<br/>
        YGC：年轻代垃圾回收次数<br/>
        FGC：老年代垃圾回收次数<br/>
        FGCT：老年代垃圾回收消耗时间<br/>
        GCT：垃圾回收消耗总时间<br/>
    </blockquote>
</script>

<!--帮助说明：-->
<script type="text/html" id="gcmetacapacityHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        MCMN:最小元数据容量 <br/>
        MCMX：最大元数据容量 <br/>
        MC：当前元数据空间大小 <br/>
        CCSMN：最小压缩类空间大小 <br/>
        CCSMX：最大压缩类空间大小 <br/>
        CCSC：当前压缩类空间大小 <br/>
        YGC：年轻代垃圾回收次数 <br/>
        FGC：老年代垃圾回收次数 <br/>
        FGCT：老年代垃圾回收消耗时间 <br/>
        GCT：垃圾回收消耗总时间
    </blockquote>
</script>

<!--帮助说明：-->
<script type="text/html" id="gcutilHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        S0：幸存1区当前使用比例<br/>
        S1：幸存2区当前使用比例<br/>
        E：伊甸园区使用比例<br/>
        O：老年代使用比例<br/>
        M：元数据区使用比例<br/>
        CCS：压缩使用比例<br/>
        YGC：年轻代垃圾回收次数<br/>
        FGC：老年代垃圾回收次数<br/>
        FGCT：老年代垃圾回收消耗时间<br/>
        GCT：垃圾回收消耗总时间
    </blockquote>
</script>

<!--帮助说明：-->
<script type="text/html" id="printcompilationHelpTip">
    <blockquote class="layui-elem-quote layui-bg-gray">
        Compiled：最近编译方法的数量<br/>
        Size：最近编译方法的字节码数量<br/>
        Type：最近编译方法的编译类型<br/>
        Method：方法名标识<br/>
    </blockquote>
</script>
</body>
</html>